package scheduler;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * A stub for your secondScheduler1.java scheduler code
 */
public class Scheduler2 implements Scheduler {

	/**
	 * @see scheduler.Scheduler#authors()
	 */
	public String authors() {
		String authors = new String("Lucas Cramer, 70133095 " +
				"Hyunje (Ethan) Jang, 23505092");
		return authors;
	}
	
	public ScheduleChoice[] schedule(SchedulingProblem pProblem) {
		ScheduleChoice[] schedules = randomState(pProblem);
		while (violatedConstraints(pProblem, schedules) != 0) {
			schedules = randomState(pProblem);
		}
		return schedules;
	}

	/**
	 * @see scheduler.Scheduler#schedule(scheduler.SchedulingProblem)
	 */
	public ScheduleChoice[] randomState(SchedulingProblem pProblem) {
		
		Course[] courses = pProblem.getCourseList();
		Room[] rooms = pProblem.getRoomList();
		Random rand = new Random();
		
		// We begin from a random state (i.e. random assignment of the variables, where a variable is an exam)
		// An assignment is when every course is assigned to an exam slot (date, time, room)
		
		ScheduleChoice[] currentState = new ScheduleChoice[courses.length];
		
		for (int i=0; i < currentState.length; i++) {
			int room = rand.nextInt(rooms.length);
			int day = rand.nextInt(5); // there are 5 possible days
			int time = rand.nextInt(4); // there are 4 possible times
			currentState[i] = new ScheduleChoice(courses[i], rooms[room], day, time);
		}
		
		return currentState;
	}
	
	public int violatedConstraints(SchedulingProblem pInstance, ScheduleChoice[] pSolution) {
		
		int conflicts = 0;
		
		ScheduleChoice[] schedule = pSolution;
		Course[] courseList = pInstance.getCourseList();
		Student[] studentList = pInstance.getStudentList();

		/* Check for incomplete Schedules */
		if (pSolution.length != courseList.length) {
			System.err.println("Incomplete Exam Schedule!");
			return Integer.MAX_VALUE;
		}
		/* Check for exam collisions */
		for (int i = 0; i < courseList.length; i++) {
			if (schedule[i].getDay() >= pInstance.getExamPeriod() || schedule[i].getDay() < 0) {
				System.err.println("Day " + schedule[i].getDay() + "is an impossible day (" + schedule[i].getCourse().getCourseName() + ")");
				return Integer.MAX_VALUE;
			}
			for (int j = i + 1; j < courseList.length; j++) {
				if (schedule[i].getRoom() == schedule[j].getRoom() && schedule[i].getDay() == schedule[j].getDay()
						&& schedule[i].getTimeSlot() == schedule[j].getTimeSlot()) {
					conflicts++;
				}
			}
		}
		/* Check for student conflicts */
		for (int i = 0; i < studentList.length; i++) {
			ScheduleChoice[] local = new ScheduleChoice[Student.scheduleSize];
			/* Get the scheduling choices */
			for (int j = 0; j < Student.scheduleSize; j++) {
				for (int k = 0; k < schedule.length; k++) {
					if (schedule[k].getCourse() == studentList[i].getCourse(j)) {
						local[j] = schedule[k];
					}
				}
			}
			/* Pairwise-compare */
			for (int j = 0; j < Student.scheduleSize; j++) {
				for (int k = j + 1; k < Student.scheduleSize; k++) {
					if (local[j].getTimeSlot() == local[k].getTimeSlot() && local[j].getDay() == local[k].getDay() && j != k) {
						conflicts++;
					}
				}
			}
		}
		return conflicts;
	}

}
